﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Courier.Core;
using Contour.Addons.CourierSupport.ItemProviders.Entities;
using Umbraco.Courier.Persistence.V4.NHibernate;
using Contour.Addons.CourierSupport.Helpers;

// need support for nodeid on submit 

namespace Contour.Addons.CourierSupport.Persisters
{
    [ItemCrud(typeof(Form), typeof(NHibernateProvider))]
    public class FormItem : ItemCrud
    {
        public override List<SystemItem> AvailableItems<T>(ItemIdentifier itemId)
        {
            throw new NotImplementedException();
        }

        public override bool DeleteItem<T>(ItemIdentifier itemId)
        {
            throw new NotImplementedException();
        }

        public override T PersistItem<T>(T item)
        {
            Form f = item as Form;
            bool update = false;

            List<Guid> pageIds = new List<Guid>();
            List<Guid> fieldsetIds = new List<Guid>();
            List<Guid> fieldIds = new List<Guid>();
            List<Guid> prevalueIds = new List<Guid>();

            var form = Helpers.FormHelper.Get(f.Id);
            if (form == null)
            {
                form = Helpers.FormHelper.Create(f);
                NHibernateProvider.GetCurrentSession().Save(form);
            }
            else
            {
                form = Helpers.FormHelper.Update(form, f);
                NHibernateProvider.GetCurrentSession().Update(form);
                update = true;
            }

            foreach (var p in f.Pages)
            {
                //check if exists
                var page = Helpers.PageHelper.Get(p.Id);
                pageIds.Add(p.Id);
                if (page == null)
                {
                    page = Helpers.PageHelper.Create(p, form);
                    NHibernateProvider.GetCurrentSession().Save(page);
                }
                else
                {
                    page = Helpers.PageHelper.Update(page, p, form);
                    NHibernateProvider.GetCurrentSession().Update(page);
                }

                foreach (var fs in p.FieldSets)
                {
                    fieldsetIds.Add(fs.Id);
                    var fieldset = Helpers.FieldSetHelper.Get(fs.Id);

                    if (fieldset == null)
                    {
                        fieldset = Helpers.FieldSetHelper.Create(fs, page);
                        NHibernateProvider.GetCurrentSession().Save(fieldset);
                    }
                    else
                    {
                        fieldset = Helpers.FieldSetHelper.Update(fieldset,fs, page);
                        NHibernateProvider.GetCurrentSession().Update(fieldset);
                    }

                    foreach (var fld in fs.Fields)
                    {
                        var field = Helpers.FieldHelper.Get(fld.Id);
                        fieldIds.Add(fld.Id);
                        if (field == null)
                        {
                            field = Helpers.FieldHelper.Create(fld, fieldset);
                            NHibernateProvider.GetCurrentSession().Save(field);
                        }
                        else
                        {
                            field = Helpers.FieldHelper.Update(field, fld, fieldset);
                            NHibernateProvider.GetCurrentSession().Update(field);
                        }

                        //only support for default prevalue provider
                        foreach (var pv in fld.PreValues)
                        {
                            var prevalue = Helpers.PreValueHelper.Get(new Guid(pv.Id.ToString()));
                            prevalueIds.Add(new Guid(pv.Id.ToString()));
                            if (prevalue == null)
                            {
                                prevalue = Helpers.PreValueHelper.Create(pv, field);
                                NHibernateProvider.GetCurrentSession().Save(prevalue);
                            }
                            else
                            {
                                prevalue = Helpers.PreValueHelper.Update(prevalue, pv, field);
                                NHibernateProvider.GetCurrentSession().Update(prevalue);
                            }
                        }
                    }
                }
            }

            
            if (update)
            {
                //deleted items
                List<Guid> pageIdsToDelete = new List<Guid>();
                List<Guid> fieldsetIdsToDelete = new List<Guid>();
                List<Guid> fieldIdsToDelete = new List<Guid>();
                List<Guid> prevalueIdsToDelete = new List<Guid>();
               
                foreach (var p in FormHelper.GetPages(form.Id))
                {
                    if (!pageIds.Contains(p.Id))
                        pageIdsToDelete.Add(p.Id);

                    foreach (var fs in FormHelper.GetFieldSets(p.Id))
                    {
                        if (!fieldsetIds.Contains(fs.Id))
                            fieldsetIdsToDelete.Add(fs.Id);

                        foreach (var fld in FormHelper.GetFields(fs.Id))
                        {
                            if (!fieldIds.Contains(fld.Id))
                                fieldIdsToDelete.Add(fld.Id);

                            foreach (var pv in FormHelper.GetPrevalues(fld.Id))
                            {
                                if (!prevalueIds.Contains(pv.Id))
                                    prevalueIdsToDelete.Add(pv.Id);
                            }
                        }
                    }
                }

                foreach (Guid pvId in prevalueIdsToDelete)
                {
                    var prevalue = PreValueHelper.Get(pvId);
                    if (prevalue != null)
                    {
                        prevalue.Uffield.Ufprevalues.Remove(prevalue);
                        NHibernateProvider.GetCurrentSession().Delete(prevalue);

                    }
                }

                foreach (Guid fldId in fieldIdsToDelete)
                {
                    var field = FieldHelper.Get(fldId);
                    if (field != null)
                    {
                        field.Uffieldset.Uffields.Remove(field);
                        NHibernateProvider.GetCurrentSession().Delete(field);
                    }
                }

                foreach (Guid fsId in fieldsetIdsToDelete)
                {
                    var fieldset = FieldSetHelper.Get(fsId);
                    if (fieldset != null)
                    {
                        fieldset.Ufpage.Uffieldsets.Remove(fieldset);
                        NHibernateProvider.GetCurrentSession().Delete(fieldset);
                    }
                }

                foreach (Guid pId in pageIdsToDelete)
                {
                    var page = PageHelper.Get(pId);
                    if (page != null)
                    {
                        page.Ufform.Ufpages.Remove(page);
                        NHibernateProvider.GetCurrentSession().Delete(page);
                    }
                }

                //clear cache
                Umbraco.Forms.Core.Services.CacheService.ClearCacheItem(f.Id.ToString());
            }
            return f as T;
        }

        public override T RetrieveItem<T>(ItemIdentifier itemId)
        {
            EntityClasses.Ufform f = Helpers.FormHelper.Get(itemId.Id);

            if (f == null)
                return null;

            Form item = new Form();
            item.ItemId = itemId;
            item.Id = f.Id;
            item.Name = f.Name;
            item.Created = f.Created;
            item.Indicator = f.Indicator;
            item.ShowValidationSummary = f.ShowValidationSummary;
            item.HideFieldValidation = f.HideFieldValidation;
            item.RequiredErrorMessage = f.RequiredErrorMessage;
            item.InvalidErrorMessage = f.InvalidErrorMessage;
            item.MessageOnSubmit = f.MessageOnSubmit;
            item.GoToPageOnSubmit= f.GotoPageOnSubmit; 
            item.ManualApproval = f.ManualApproval;
            item.Archived = f.Archived;
            item.StoreRecordsLocally = f.StoreRecordsLocally;
            item.DisableDefaultStylesheet = f.DisableDefaultStylesheet;

            //datasource id

            //xpath on submit comes from settings

            foreach (var p in FormHelper.GetPages(f.Id))
            {
                Page page = new Page();
                page.Caption = p.Caption;
                page.Form = f.Id;
                page.Id = p.Id;
                page.SortOrder = p.SortOrder;

                foreach (var fs in FormHelper.GetFieldSets(p.Id))
                {
                    FieldSet fieldset = new FieldSet();
                    fieldset.Id = fs.Id;
                    fieldset.Caption = fs.Caption;
                    fieldset.Page = p.Id;
                    fieldset.SortOrder = fs.SortOrder;

                    foreach (var fld in FormHelper.GetFields(fs.Id))
                    {
                        Field field = new Field();
                        field.Id = fld.Id;
                        field.Caption = fld.Caption;
                        field.DataSourceFieldKey = fld.DataSourceField;
                        field.FieldSet = fs.Id;
                        field.FieldTypeId = fld.Fieldtype;
                        field.Form = f.Id;
                        field.InvalidErrorMessage = fld.InvalidErrorMessage;
                        field.Mandatory = fld.Mandatory;
                        //field.PreValueSourceId = fld.PreValueProvider
                        field.RegEx = fld.RegEx;
                        field.RequiredErrorMessage = fld.RequiredErrorMessage;
                        field.SortOrder = fld.SortOrder;
                        field.ToolTip = fld.ToolTip;

                        if(fld.PreValueProvider != null)
                            field.PreValueSourceId = (Guid)fld.PreValueProvider;

                        foreach (var pv in FormHelper.GetPrevalues(fld.Id))
                        {
                            PreValue prevalue = new PreValue();
                            prevalue.Id = pv.Id;
                            if(pv.SortOrder != null)
                                prevalue.SortOrder = (int)pv.SortOrder;
                            prevalue.Value = pv.Value;
                            prevalue.Field = fld.Id;

                            field.PreValues.Add(prevalue);
                        }

                        fieldset.Fields.Add(field);
                    }

                    page.FieldSets.Add(fieldset);
                }

                item.Pages.Add(page);
            }

            return item as T;
        }
    }
}